package edu.ncsu.csc.itrust.action;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.collections.comparators.ReverseComparator;
import edu.ncsu.csc.itrust.beans.PatientReferralBean;
import edu.ncsu.csc.itrust.beans.PatientBean;
import edu.ncsu.csc.itrust.beans.PersonnelBean;
import edu.ncsu.csc.itrust.dao.DAOFactory;
import edu.ncsu.csc.itrust.dao.mysql.PatientDAO;
import edu.ncsu.csc.itrust.dao.mysql.PersonnelDAO;
import edu.ncsu.csc.itrust.dao.mysql.TransactionDAO;
import edu.ncsu.csc.itrust.dao.mysql.PatientReferralDAO;
import edu.ncsu.csc.itrust.exception.DBException;
import edu.ncsu.csc.itrust.exception.iTrustException;

/**
 * Used for referring patients to other HCPs. 
 */
public class PatientReferralAction {
	private long loggedInMID;
	private TransactionDAO transDAO;
	private PatientReferralDAO PatientReferralDAO;
	private PatientDAO patDAO;
	private PersonnelDAO perDAO;
	
	/**
	 * Super class validates the patient id
	 * 
	 * @param factory The DAOFactory used to create the DAOs used in this action.
	 * @param loggedInMID The MID of the user managing this referral.
	 * @param pidString The MID of the patient being referred.
	 * @throws iTrustException
	 */
	public PatientReferralAction(DAOFactory factory, long loggedInMID) throws iTrustException {
		this.PatientReferralDAO = factory.getPatientReferralsDAO();
		this.patDAO = factory.getPatientDAO();
		this.perDAO = factory.getPersonnelDAO();
		this.transDAO =  factory.getTransactionDAO();
		this.loggedInMID = loggedInMID;

	}
	
	/**
	 * Adds a PatientReferralsBeans to the database.
	 * @param r The PatientReferralsBean to be added.
	 * @throws DBException
	 */
	public void sendReferral(PatientReferralBean r) throws DBException {
		PatientReferralDAO.addReferral(r);
	}
	
	/**
	 * Deletes a Patient Referral from the database .
	 * @param r The current PatientReferralsBeans.
	 * @throws DBException
	 */
	public void deleteReferral(PatientReferralBean r) throws DBException {
		PatientReferralDAO.removeReferral(r.getId());
	}
	
	/**
	 * Updates an existing PatientReferralsBean.
	 * @param r The current PatientReferralsBeans.
	 * @throws DBException
	 */
	public void updateReferral(PatientReferralBean r) throws DBException {
		PatientReferralDAO.editReferral(r);
	}
	
	/**
	 * Gets the referrals the currently logged in MID has sent.
	 * @return A java.util.List of PatientReferralsBeans this MID has sent.
	 * @throws DBException
	 */
	public List<PatientReferralBean> getReferralsSentFromMe() throws DBException {
		return PatientReferralDAO.getReferralsSentFrom(loggedInMID);
	}
	
	/**
	 * Gets the referrals this MID has received.
	 * @return A java.util.List of the PatientReferralsBeans this MID has received.
	 * @throws DBException
	 */
	public List<PatientReferralBean> getReferralsSentToMe() throws DBException {
		return PatientReferralDAO.getReferralsSentTo(loggedInMID);
	}
	
	/**
	 * Gets the referrals this MID has received for a patient.
	 * @return A java.util.List of the PatientReferralsBeans this MID has received.
	 * @throws DBException
	 */
	public List<PatientReferralBean> getReferralsForPatient(Long pid) throws DBException {
		return PatientReferralDAO.getReferralsForPatient(pid);
	}
	
	/**
	 * Gets the referrals for a specific Office Visit
	 * @return A java.util.List of the PatientReferralsBeans this MID has received.
	 * @throws DBException
	 */
	public List<PatientReferralBean> getReferralsForOfficeVisit(int ovid) throws DBException {
		return PatientReferralDAO.getReferralsForOfficeVisit(ovid);
	}
	
	/**
	 * Gets a single referral
	 * @return the PatientReferralsBean that has this unique ID has received.
	 * @throws DBException
	 */
	public PatientReferralBean getReferral(int id) throws DBException {
		return PatientReferralDAO.getPatientReferral(id);
	}
	
	class PatientName implements Comparator<PatientReferralBean>{

		public int compare(PatientReferralBean arg0, PatientReferralBean arg1) {
			PatientReferralBean pat1 = (PatientReferralBean) arg0;
			PatientReferralBean pat2 = (PatientReferralBean) arg1;
			PatientBean patient1 = null;
			PatientBean patient2 = null;
			try {
				patient1 = patDAO.getPatient(pat1.getPatientID());
				patient2 = patDAO.getPatient(pat2.getPatientID());
			} catch (DBException e) {
				e.printStackTrace();
			} 
			return patient1.getFullName().compareTo(patient2.getFullName());
		}
	}
	
	class HCPName implements Comparator<PatientReferralBean>{

		public int compare(PatientReferralBean arg0, PatientReferralBean arg1) {
			PatientReferralBean pat1 = (PatientReferralBean) arg0;
			PatientReferralBean pat2 = (PatientReferralBean) arg1;
			PersonnelBean personnel1 = null;
			PersonnelBean personnel2 = null;
			try {
				personnel1 = perDAO.getPersonnel(pat1.getReceiverID());
				personnel2 = perDAO.getPersonnel(pat2.getReceiverID());
			} catch (DBException e) {
				e.printStackTrace();
			} 
			return personnel1.getFullName().compareTo(personnel2.getFullName());
		}
		
	}
	
	class Priority implements Comparator<PatientReferralBean>{

		public int compare(PatientReferralBean o1, PatientReferralBean o2) {
			PatientReferralBean pat1 =(PatientReferralBean) o1;
			PatientReferralBean pat2 =(PatientReferralBean) o2;
			if(pat1.getPriority() > pat2.getPriority()){
				return 1;
			}
			else if(pat1.getPriority() < pat2.getPriority()){
				return -1;
			}
			else{
				return 0;
			}
		}	
	}
	
	class Time implements Comparator<PatientReferralBean>{

		public int compare(PatientReferralBean o1, PatientReferralBean o2) {
			PatientReferralBean pat1 =(PatientReferralBean) o1;
			PatientReferralBean pat2 =(PatientReferralBean) o2;
			return pat1.getDateAdded().compareTo(pat2.getDateAdded());
		}	
	}
	
	public List<PatientReferralBean> sort(String sortby, String orderby, String person) throws DBException{
		List<PatientReferralBean> list = null;
		if(!person.equals("")){
			list = PatientReferralDAO.getReferralsForPatient(Long.parseLong(person));

		}
		else{
			list = PatientReferralDAO.getReferralsSentFrom(loggedInMID);

		}
		ReverseComparator reverse = null;
		if(sortby.equals("name")){
			if(orderby.equals("asce")){
				Collections.sort(list, new PatientName());
			}
			else{
				reverse = new ReverseComparator(new PatientName());
				Collections.sort(list, reverse);
			}
		}
		
		if(sortby.equals("hcp")){
			if(orderby.equals("asce")){
				Collections.sort(list, new HCPName());
			}
			else{
				reverse = new ReverseComparator(new HCPName());
				Collections.sort(list, reverse);
			}
		}
		
		if(sortby.equals("priority")){
			if(orderby.equals("asce")){
				Collections.sort(list, new Priority());
			}
			else{
				reverse = new ReverseComparator(new Priority());
				Collections.sort(list, reverse);
			}
		}
		
		if(sortby.equals("time")){
			if(orderby.equals("asce")){
				Collections.sort(list, new Time());
			}
			else{
				reverse = new ReverseComparator(new Time());
				Collections.sort(list, reverse);
			}
		}
		
		return list;
	}
}
